﻿using System;
using System.Collections.Generic;
#if SILVERLIGHT
using System.Windows;
using System.Windows.Controls.Primitives;
#else
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls.Primitives;
#endif

namespace Microsoft.PlayerFramework
{
    /// <summary>
    /// Behavior to support binding commands to this IsChecked property of a ToggleButton control.
    /// This is required to bind a property to the IsChecked property without the Binding getting disconnected when the user checks or unchecks the control.
    /// </summary>
    public static class IsCheckedBehavior
    {
        /// <summary>
        /// Identifies the Value dependency property.
        /// </summary>
        public static readonly DependencyProperty ValueProperty = DependencyProperty.RegisterAttached("Value", typeof(bool), typeof(IsCheckedBehavior), new PropertyMetadata(false, Attach));

        /// <summary>
        /// Sets the value to the IsChecked property of the ToggleButton control
        /// </summary>
        /// <param name="obj">The dependency object to set the IsChecked property on. This should always be a ToggleButton</param>
        /// <param name="propertyValue">The Value to set.</param>
        public static void SetValue(DependencyObject obj, bool propertyValue)
        {
            if (obj == null) throw new ArgumentNullException("obj");
            obj.SetValue(ValueProperty, propertyValue);
        }

        /// <summary>
        /// Gets the value from with the ToggleButton's IsChecked property
        /// </summary>
        /// <param name="obj">The ToggleButton control to get the IsChecked property for.</param>
        /// <returns>The value associated with the IsChecked property of the ToggleButton</returns>
        public static bool GetValue(DependencyObject obj)
        {
            if (obj == null) throw new ArgumentNullException("obj");
            return (bool)obj.GetValue(ValueProperty);
        }

        static Dictionary<ToggleButton, Action> DetachActions = new Dictionary<ToggleButton, Action>();

        static void Attach(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var control = d as ToggleButton;
            if (control != null)
            {
                var oldValue = e.OldValue;
                var newValue = e.NewValue;
                if (DetachActions.ContainsKey(control)) DetachToggle(control);
                AttachToggle(control, (bool)newValue);
            }
        }

        static void AttachToggle(ToggleButton control, bool newValue)
        {
            control.IsChecked = newValue;
            control.Checked += toggle_Checked;
            control.Unchecked += toggle_Unchecked;
            DetachActions.Add(control, () =>
            {
                control.Checked -= toggle_Checked;
                control.Unchecked -= toggle_Unchecked;
            });
        }

        static void DetachToggle(ToggleButton toggleButton)
        {
            var action = DetachActions[toggleButton];
            action();
            DetachActions.Remove(toggleButton);
        }

        static void toggle_Unchecked(object sender, RoutedEventArgs e)
        {
            SetValue(sender as DependencyObject, false);
        }

        static void toggle_Checked(object sender, RoutedEventArgs e)
        {
            SetValue(sender as DependencyObject, true);
        }
    }
}
